"""
使用ViewSet来演示自定义视图方法映射
"""
from rest_framework.viewsets import ViewSet,ModelViewSet
from rest_framework.response import Response
from rest_framework.decorators import action
from .serializers import *
from .models import *
from rest_framework.authentication import SessionAuthentication
from rest_framework.permissions import IsAdminUser,IsAuthenticated,AllowAny
from rest_framework.throttling import ScopedRateThrottle,UserRateThrottle
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.filters import OrderingFilter

class HerosViewSet(ModelViewSet):
    """
    list:
    序列化返回列表英雄数据！

    create:
    反序列化新建单一数据！
    """


    queryset = HeroInfo.objects.all()
    serializer_class = HeroInfoModelSerializer

    # 在针对的视图类中局部指定自定义的限流规则
    throttle_scope = "download"
    # 局部指定限流后端
    throttle_classes = [ScopedRateThrottle]



# 自定义第一种分页后端
from rest_framework.pagination import PageNumberPagination
class MyPageNumpagination(PageNumberPagination):
    page_query_param = "page" # books/?page=2
    page_size = 5 # 自定义设置每页几个
    max_page_size = 10 # 每页最大数量
    page_size_query_param = "page_size" # books/?page=2&page_size=5



# 自定义第二种分页后端
from rest_framework.pagination import LimitOffsetPagination
class MyLimitOffsetPagination(LimitOffsetPagination):
    limit_query_param = "limit" # /books/?limit=5 表示取几条数据
    offset_query_param = "offset" # /books/?offset=3&limit=5 表示偏移量
    max_limit = 10 # 每页最大数量


class BooksViewSet(ModelViewSet):
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoModelSerializer

    # 局部设置分页器
    # pagination_class = MyPageNumpagination
    pagination_class = MyLimitOffsetPagination


    # 自定义当前视图中使用的身份认证后端
    authentication_classes = [SessionAuthentication]
    # 局部定义当前视图中使用的权限检查后端
    permission_classes = [AllowAny]

    # 所有设置在局部中定义为空列表，那么就相当于取消此功能
    throttle_classes = []
    # 在针对的视图类中局部指定自定义的限流规则
    throttle_scope = "upload"

    # 局部指定过滤后端
    filter_backends = [DjangoFilterBackend, OrderingFilter]
    # 在局部中指定过滤依据的字段
    # filter_fields = ['btitle', 'bpub_date', 'bread']
    filterset_fields = ['btitle', 'bpub_date', 'bread']
    # 指定排序过滤的依据字段
    ordering_fields = ['bpub_date', 'bread', 'bcomment']

    # 需求：修改书本的阅读量,部分更新
    # PATCH + /books/<pk>/ = self.read
    # 自定义方法read实现修改阅读量,自定义方法不会自动帮助我们构建映射，需要对它添加装饰
    # 自定义函数默认映射的规则是：
    #   (1)、当detail为True的时候：  视图集映射前缀 + (?P<pk>\d+) + 函数名称/url_path
    #   (2)、当detail为False的时候：  视图集映射前缀 + 函数名称/url_path
    @action(methods=['patch'], detail=True) # , url_path='fix_read')
    def read(self, request, pk):

        # 这一行代码会抛出ZeroDevisionError异常，不是DRF定义的异常
        # a = 10 / 0
        # 如果此处我抛出一个DRF的异常
        # raise serializers.ValidationError({'errmsg': '校验失败！'})


        # request.data = {"bread": 100}
        book = BookInfo.objects.get(pk=pk)


        bs = BookInfoModelSerializer(
            instance=book,
            data=request.data,
            partial=True
        )

        # if not bs.is_valid():
        #     raise serializers.ValidationError(bs.errors)
        # raise_exception=True，如果校验失败会直接在视图中抛出ValidationError异常，那么DRF视图会自行捕获并构建合适的响应返回
        bs.is_valid(raise_exception=True)

        bs.save()

        return Response(bs.data)